package main

import (
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/xuri/excelize/v2"
)

type ExportReportFormHeader struct {
	FormID    string                   `json:"form_id"`
	Label     string                   `json:"label"`
	SubHeader []ExportReportFormHeader `json:"sub_header"`
}

var headerStr = `[{"form_id":"sys_task_status","label":"状态"},{"form_id":"table3","label":"表格111","sub_header":[{"form_id":"textarea3","label":"多行文本2"},{"form_id":"input5","label":"单行文本2"}]},{"form_id":"table4","label":"表格222","sub_header":[{"form_id":"input6","label":"单行文本23"}]},{"form_id":"input1","label":"单行文本"},{"form_id":"textarea2","label":"多行文本2weqwqeqweqweqweqweqwe"}]`

var data = `[{"input1":"asdf","serial_num":"010","sys_task_status":"进行中","table3":[{"input5":"adsf","textarea3":"asdf"},{"input5":"a111","textarea3":"11111"}],"table4":[{"input6":"dfgh"}],"textarea2":"asdf","update_at":"2023-10-16 14:16:38"},{"input1":"1","serial_num":"009","sys_task_status":"进行中","textarea2":"2","update_at":"2023-10-13 11:30:45"},{"input1":"1","serial_num":"008","sys_task_status":"进行中","textarea2":"2","update_at":"2023-10-12 10:30:25"},{"input1":"1","serial_num":"007","sys_task_status":"进行中","textarea2":"2","update_at":"2023-10-11 17:48:38"},{"input1":"1","serial_num":"006","sys_task_status":"进行中","textarea2":"2","update_at":"2023-10-10 16:55:47"},{"input1":"1","serial_num":"005","sys_task_status":"进行中","textarea2":"2","update_at":"2023-10-10 14:49:56"},{"input1":"666","serial_num":"004","sys_task_status":"进行中","textarea2":"","update_at":"2023-10-09 15:19:59"},{"input1":"111","serial_num":"003","sys_task_status":"进行中","textarea2":"","update_at":"2023-10-09 15:16:21"},{"input1":"2","serial_num":"002","sys_task_status":"进行中","textarea2":"","update_at":"2023-10-07 14:50:10"},{"input1":"1","serial_num":"001","sys_task_status":"已完成","textarea2":"","update_at":"2023-10-07 14:50:00"}]`

func main() {
	f := excelize.NewFile()
	var sheetName = "Sheet1"
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	fields, err := handleHeader(f, sheetName)
	if err != nil {
		panic(err)
	}
	handleData(f, sheetName, fields)
	// 根据指定路径保存文件
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}
}

// 设置 excel 的 header
func handleHeader(f *excelize.File, sheetName string) (fields []string, err error) {
	var headers []ExportReportFormHeader
	if err := json.Unmarshal([]byte(headerStr), &headers); err != nil {
		return nil, err
	}
	for idx, header := range headers {
		if header.SubHeader == nil {
			var subHeader []ExportReportFormHeader
			subHeader = append(subHeader, ExportReportFormHeader{
				FormID:    header.FormID,
				Label:     header.Label,
				SubHeader: nil,
			})
			header.SubHeader = subHeader
			headers[idx] = header
		}
		if len(header.SubHeader) == 0 {
			fields = append(fields, header.FormID)
		}

		for _, v := range header.SubHeader {
			fields = append(fields, v.FormID)
		}
	}

	// 定义 header 的两行
	var h1, h2 = []string{}, []string{}

	for _, v := range headers {
		for _, sb := range v.SubHeader {
			h1 = append(h1, v.Label)
			h2 = append(h2, sb.Label)
		}
	}
	// 先插入一行
	cell1, err := excelize.CoordinatesToCellName(1, 1)
	if err != nil {
		return nil, err
	}

	// 计算第一列的合并数据
	f.SetSheetRow(sheetName, cell1, &h1)
	// 合并 header
	var tmpVal string
	var tmpIdx int
	for i := 0; i < len(h1); i++ {
		if tmpVal != h1[i] {
			step := i - tmpIdx
			if step == 0 {
				continue
			}

			// fmt.Printf("-- 步长 %d; tmpIdx = %d; tmpVal = %s; i = %d \n", step, tmpIdx, tmpVal, i)
			var start string
			start, err = excelize.ColumnNumberToName(i - step + 1)
			if err != nil {
				return nil, err
			}

			end, _ := excelize.ColumnNumberToName(i)
			if err != nil {
				return nil, err
			}
			start = fmt.Sprintf("%s1", start)
			end = fmt.Sprintf("%s1", end)
			if err = f.MergeCell(sheetName, start, end); err != nil {
				return nil, err
			}
			tmpVal = h1[i]
			tmpIdx = i
		}
	}

	cell2, err := excelize.CoordinatesToCellName(1, 2)
	if err != nil {
		return nil, err
	}
	f.SetSheetRow(sheetName, cell2, &h2)
	// 设置完成第二行的数据，再次合并单元格
	for idx, v := range h1 {
		if h2[idx] == v {
			colName, _ := excelize.ColumnNumberToName(idx + 1)
			start := fmt.Sprintf("%s%d", colName, 1)
			end := fmt.Sprintf("%s%d", colName, 2)
			if err := f.MergeCell(sheetName, start, end); err != nil {
				return nil, err
			}
		}
	}
	return
}

// 设置 excel 的数据
func handleData(f *excelize.File, sheetName string, fields []string) {
	type dataType []map[string]interface{}
	var dataRow dataType
	if err := json.Unmarshal([]byte(data), &dataRow); err != nil {
		panic(err)
	}
	fmt.Printf("%+v \n", fields)
	var sequenceIdx = 2
	for idx, mv := range dataRow {
		var maxRow = 1
		var maxRowField = "" // 数据最大的子表
		var subTableFields []string
		var subFieldMap = make(map[string]struct{})
		// 简单字段
		var simpleData = make(map[string]interface{})
		// 子表字段
		var subTableData = make(map[string][]map[string]interface{})
		for _, field := range fields {
			if v, ok := mv[field]; ok {
				simpleData[field] = v
			}
		}
		// 子表数据
		for subField, vd := range mv {
			if reflect.TypeOf(vd).Kind() == reflect.Slice {
				subTableFields = append(subTableFields, subField)
				// 子表数据
				var subData []map[string]interface{}
				dd := vd.([]interface{})
				if maxRow < len(dd) {
					maxRow = len(dd)
					maxRowField = subField
				}
				for _, vv := range dd {
					var mi = vv.(map[string]interface{})
					subData = append(subData, mi)
				}
				// 这里需要插入数据
				subTableData[subField] = append(subTableData[subField], subData...)
			}
			_ = fmt.Sprintln(idx)
		}
		// var rData []interface{} // 行数据
		// fmt.Println(subTableFields, maxRowField)
		// fmt.Printf("%+v \n", subTableData[maxRowField])
		if _, ok := subTableData[maxRowField]; ok {
			for idx, v := range subTableData[maxRowField] {
				// 每行的数据
				var rowD = make(map[string]interface{})
				for _, sf := range subTableFields {
					if sf != maxRowField {
						if len(subTableData[sf]) > idx {
							// 相同层级
							for f, stdV := range subTableData[sf][idx] {
								rowD[f] = stdV
								subFieldMap[f] = struct{}{}
							}
						}
					}
				}
				for f, stdV := range v {
					rowD[f] = stdV
					subFieldMap[f] = struct{}{}
				}
				for f, v := range simpleData {
					rowD[f] = v
				}

				// 插入一行
				sequenceIdx += 1
				cell1, err := excelize.CoordinatesToCellName(1, sequenceIdx)
				if err != nil {
					panic(err)
				}
				var rowData []interface{}
				for _, fv := range fields {
					if v, ok := rowD[fv]; ok {
						rowData = append(rowData, v)
					} else {
						rowData = append(rowData, "")
					}
				}
				f.SetSheetRow(sheetName, cell1, &rowData)
			}
			// 需要计算和并列
			for idx, fi := range fields {
				if _, ok := subFieldMap[fi]; !ok {
					var hCell = ""
					var vCell = ""
					hCellPrefix, _ := excelize.ColumnNumberToName(idx + 1)
					hCell = fmt.Sprintf("%s%d", hCellPrefix, sequenceIdx-2+1)
					maxRowPrefix, _ := excelize.ColumnNumberToName(idx + 1)
					vCell = fmt.Sprintf("%s%d", maxRowPrefix, sequenceIdx)
					fmt.Println(hCell, vCell)
					f.MergeCell(sheetName, hCell, vCell)
				}
			}
		} else {
			sequenceIdx += 1
			var rowData []interface{}
			for _, fv := range fields {
				if v, ok := simpleData[fv]; ok {
					rowData = append(rowData, v)
				} else {
					rowData = append(rowData, "")
				}
			}
			// 插入一行
			cell, err := excelize.CoordinatesToCellName(1, sequenceIdx)
			if err != nil {
				panic(err)
			}
			// 计算第一列的合并数据
			f.SetSheetRow(sheetName, cell, &rowData)
		}

		// 没完成一行数据的渲染需要合并单元格
		fmt.Println(subTableFields, maxRowField)
		// fmt.Println(simpleData)
		// 先插入一行
		// cell1, err := excelize.CoordinatesToCellName(1, idx+3)
		// if err != nil {
		// 	panic(err)
		// }
		// 计算第一列的合并数据
		// f.SetSheetRow(sheetName, cell1, &rData)
		// if idx == 0 {
		// 	break
		// }
	}
}
